package com.xxwy.ddu.security.browser.config;

import com.xxwy.ddu.security.browser.config.handler.BrowserLogoutSuccessHandler;
import com.xxwy.ddu.security.code.authonrize.AuthorizeConfigManager;
import com.xxwy.ddu.security.code.config.PasswordAuthenticationConfig;
import com.xxwy.ddu.security.code.config.SmsCodeAuthenticationConfig;
import com.xxwy.ddu.security.code.properties.SecurityProperties;
import com.xxwy.ddu.security.code.vaildatecode.config.ValidateCodeSecurityConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.session.InvalidSessionStrategy;
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.social.security.SpringSocialConfigurer;

import javax.sql.DataSource;

/**
 * @author xxwy
 * on 2018/8/24 0024
 */
@EnableRedisHttpSession
@Configuration
public class BrowerSecurityConfig extends PasswordAuthenticationConfig {


    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    private SmsCodeAuthenticationConfig smsCodeAuthenticationConfig;

    @Autowired
    private SpringSocialConfigurer xxSocialConfigurer;

    @Autowired
    private SessionInformationExpiredStrategy sessionInformationExpiredStrategy;

    @Autowired
    private InvalidSessionStrategy invalidSessionStrategy;

    @Autowired
    private DataSource dataSource;

    @Autowired
    UserDetailsService userDetailsService;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    ValidateCodeSecurityConfig validateCodeSecurityConfig;

    @Autowired
    private AuthorizeConfigManager authorizeConfigManager;

    @Autowired
    private BrowserLogoutSuccessHandler browserLogoutSuccessHandler;


    /**
     * Token放入DB中,指定数据源的
     *
     * @return
     */
    @Bean
    @ConditionalOnClass(DataSource.class)
    public PersistentTokenRepository persistentTokenRepository(DataSource dataSource) {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        //放入数据源
        jdbcTokenRepository.setDataSource(dataSource);
        //自动帮我创建表,自己生成变比较好
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/**/*.css", "/**/*.js", "/**/*.png","/**/*.jpg", "/favicon.ico","/webjars/**");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }

    /**
     * 定制规则
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //表单验证
        applyPasswordAuthenticationConfig(http);
        //加上验证码的校验
        http.apply(validateCodeSecurityConfig).and()
                //手机登录
                .apply(smsCodeAuthenticationConfig).and()
                //第三方登录
                .apply(xxSocialConfigurer).and()
                //logout
                .logout()
                    .logoutUrl(securityProperties.getBrowser().getSignOut())
                    .deleteCookies("JSESSIONID")
                    .logoutSuccessHandler(browserLogoutSuccessHandler).and()
                //允许跳转请求
                .headers().frameOptions().disable().and()
                .csrf().disable()
                //session管理
                .sessionManagement()
                    .invalidSessionStrategy(invalidSessionStrategy)
                    .maximumSessions(securityProperties.getBrowser().getSession().getMaximumSessions())
                    //如果达到最大登录数，不让后面的用户登录
                    .maxSessionsPreventsLogin(securityProperties.getBrowser().getSession().isMaxSessionsPreventsLogin())
                    .expiredSessionStrategy(sessionInformationExpiredStrategy);
        authorizeConfigManager.config(http.authorizeRequests());
        //remember-me
        if (securityProperties.getBrowser().isRememberMe() ) {
            http.rememberMe()
                    .tokenRepository(persistentTokenRepository(dataSource))
                    .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
                    .userDetailsService(userDetailsService);
        }
    }


}


